package engine.render;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.TreeMap;
import static engine.GL.*;

public class Shader 
{

    private boolean useShader;
    public boolean usingShader() 
    {
        return useShader;
    }
    
    private int programID;
    public int getProgramID() 
    {
        return programID;
    }
    
    private int vertShader;
    private int fragShader;
    
    private String fileName;
    public String getShaderName() 
    {
        return fileName;
    }
    
    private TreeMap<String, Integer> uniformLocs;

    public Shader(String filename) 
    {
        fileName = filename;
        uniformLocs = new TreeMap<String, Integer>();
        programID = createProgram();
        useShader = true;
        if (programID != 0) 
        {
            vertShader = createVertShader(fileName + ".vert");
            fragShader = createFragShader(fileName + ".frag");
        } 
        else 
        {
            useShader = false;
        }
        if (vertShader != 0 && fragShader != 0) 
        {
            attachShader(programID, vertShader);
            attachShader(programID, fragShader);
            linkProgram(programID);
            validateProgram(programID);
        } else {
            useShader = false;
        }
    }
    
    public void bind() 
    {
        if (useShader) 
        {
            useProgram(programID);
        }
    }
    
    public void release() 
    {
        if (useShader) 
        {
            releaseProgram();
        }
    }
    
    public void setUniform(String uniformName, float val) 
    {
        if (!uniformLocs.containsKey(uniformName)) 
        {
            int location = getUniformLocation(programID, uniformName);
            uniformLocs.put(uniformName, location);
        }
        uniform(uniformLocs.get(uniformName), val);
    }
    
    public void bindUniform(String uniformName, float x0, float x1, float x2) 
    {
        if (!uniformLocs.containsKey(uniformName)) 
        {
            int location = getUniformLocation(programID, uniformName);
            uniformLocs.put(uniformName, location);
        }
        uniform(uniformLocs.get(uniformName), x0, x1, x2);
    }

    // REMOVE
    public int attribLocation(String attribName) 
    {
        return getAttribLocation(programID, attribName);
    }
    // END REMOVE

    private int createVertShader(String filename) 
    {
        vertShader = createShader(VERTEX_SHADER);
        if (vertShader == 0) 
        {
            return 0;
        }
        String vertexCode = "";
        String line;
        try 
        {
            BufferedReader reader = new BufferedReader(new FileReader(filename));
            while ((line = reader.readLine()) != null) 
            {
                vertexCode += line + "\n";
            }
        } 
        catch (Exception e) 
        {
            System.out.println("Failure reading vertex shader code");
            System.out.println(e);
            return 0;
        }
        shaderSource(vertShader, vertexCode);
        compileShader(vertShader);
        return vertShader;
    }

    private int createFragShader(String filename) 
    {
        fragShader = createShader(FRAGMENT_SHADER);
        if (fragShader == 0) 
        {
            return 0;
        }
        String fragCode = "";
        String line;
        try 
        {
            BufferedReader reader = new BufferedReader(new FileReader(filename));
            while ((line = reader.readLine()) != null) 
            {
                fragCode += line + "\n";
            }
        } 
        catch (Exception e) 
        {
            System.out.println("Failure reading fragment shader code");
            System.out.println(e);
            return 0;
        }
        shaderSource(fragShader, fragCode);
        compileShader(fragShader);
        return fragShader;
    }

}